package com.bangcommunity.bbframe.sdm.utils;

import com.bangcommunity.bbframe.common.base.BaseResult;
import com.bangcommunity.bbframe.common.utils.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.UUID;

public class RequestUtils {
    private static Logger logger = LoggerFactory.getLogger(RequestUtils.class);

    public static boolean isAjaxRequest(HttpServletRequest request) {
        String xRequestedWith = request.getHeader("X-Requested-With");
        return StringUtils.isNotBlank(xRequestedWith);
    }

    public static boolean canResponseJsonForAjax(HttpServletRequest request) {
        if (!isAjaxRequest(request)) {
            return false;
        }
        String accept = request.getHeader("Accept");
        return accept != null && accept.contains("application/json");
    }

    public static void renderBaseResult(ServletResponse response, BaseResult result) {
        try {
            HttpServletResponse res = (HttpServletResponse) response;
            res.setHeader("Content-Type", "application/json;charset=utf-8");
            PrintWriter out = res.getWriter();
            JacksonUtil jsonMapper = new JacksonUtil();
            out.write(jsonMapper.toJson(result));
            out.flush();
            out.close();
        } catch (IOException e) {
            logger.error("renderWebResult exception:", e);
        }
    }

    public static String paramsMapToURLString(Map<String, String> params, String prefix)
            throws UnsupportedEncodingException {
        if (params == null || params.isEmpty()) {
            return "";
        }

        StringBuilder ex = new StringBuilder(prefix);
        for (Map.Entry<String, String> entry : params.entrySet()) {
            ex.append(entry.getKey() + "=" + getURLEncoderValue(entry.getValue()));
            ex.append("&");
        }
        ex.delete(ex.length() - 1, ex.length());
        return ex.toString();
    }

    private static String getURLEncoderValue(String data) throws UnsupportedEncodingException {
        if (!StringUtils.isEmpty(data))
            return URLEncoder.encode(data, "utf-8");
        else
            return "";
    }

    public static String extractParam(HttpServletRequest request, String key) throws NullPointerException {

        String val = request.getParameter(key);
        if (StringUtils.isNotBlank(val)) {
            return val;
        }

        Cookie cookie = getCookieFromRequest(request, key);
        if (null != cookie && StringUtils.isNotBlank(cookie.getValue())) {
            return cookie.getValue();
        }
        val = request.getHeader(key);
        if (StringUtils.isNotBlank(val)) {
            return val;
        }
        return null;

    }

    public static Cookie getCookieFromRequest(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return null;
        }
        for (Cookie cookie : cookies) {
            if (cookie.getName().equalsIgnoreCase(name))
                return cookie;
        }

        return null;

    }

    public static void addCookieToResponse(HttpServletResponse response, Cookie... cookies) {
        for (Cookie cookie : cookies) {
            response.addCookie(cookie);
        }
    }

    public static void removeCookieToResponse(HttpServletResponse response, String name) {
        Cookie cookie = new Cookie(name, null);
        cookie.setMaxAge(0);
        cookie.setPath("/");

        addCookieToResponse(response, cookie);
    }

    private static final ThreadLocal<String> requestIdThreadLocal = new ThreadLocal<>();

    public static String getRequestId() {
        String requestId = requestIdThreadLocal.get();
        if (StringUtils.isBlank(requestId)) {
            requestId = UUID.randomUUID().toString();
            requestIdThreadLocal.set(requestId);
        }
        return requestId;
    }

    public static void clearRequestId() {
        requestIdThreadLocal.remove();
    }

    public static boolean isIos(HttpServletRequest request) {
        OSTypeEnum osType = getOsType(request);
        return null != osType && osType.equals(OSTypeEnum.ios);
    }

    public static OSTypeEnum getOsType(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            logger.warn("UA不存在,uri:{},ip:{}", request.getRequestURI(), request.getRemoteAddr());
            return OSTypeEnum.other;
        }
        if ((userAgent.contains("iPhone") || userAgent.contains("iPad") || userAgent.contains("iPod"))) {
            return OSTypeEnum.ios;
        } else if (userAgent.contains("Android")) {
            return OSTypeEnum.android;
        } else {
            return OSTypeEnum.other;
        }
    }

    public static BrowerEnum getBrowerType(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            logger.warn("UA不存在,uri:{},ip:{}", request.getRequestURI(), request.getRemoteAddr());
            return BrowerEnum.other;
        }
        if (userAgent.contains(" QQ")) {
            return BrowerEnum.qq;
        } else if (userAgent.contains(" MicroMessenger")) {
            return BrowerEnum.weixin;
        } else if (userAgent.contains(" Weibo")) {
            return BrowerEnum.sina_weibo;
        } else if (userAgent.contains(" AliApp(LW")) {
            return BrowerEnum.ali_laiwang;
        } else if (userAgent.contains(" AliApp(TB")) {
            return BrowerEnum.ali_taobao;
        } else {
            return BrowerEnum.other;
        }
    }

    public static String getParaStr(HttpServletRequest request) {
        StringBuffer para = new StringBuffer("");
        Enumeration parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String key = (String) parameterNames.nextElement();
            String value = Arrays.toString(request.getParameterValues(key));
            if (para.length() == 0) {
                para.append(key + "=" + value);
            } else {
                para.append("|" + key + "=" + value);
            }
        }
        return para.toString();
    }
}
